//--------------------------------------------------
/**
 *
 *      Hand Gesture Recognition System
 *
 */
//--------------------------------------------------
/**
 * //MANAGEDATASET CLASS//
 * Librería de captura, pre-procesamiento y procesamiento del DataSet
 *
 * @author Edwin Cobos & Cesar Murcia
 * @version ManageDataSet_v1.3
 *
 * Revisado: 12/11/11
 */
//--------------------------------------------------
//PACKAGE//
package HGR.Learning;
//IMPORT//
import HGR.Core;
import OpenCV.cv;
import OpenCV.cv.IplImage;
import SIFT.SIFT_ExtractPointRoi;
import SIFT.util.FloatArray2D;
import SURF.Save_Interest_Points_To_File;
import SURF.Surf;
import com.sun.jna.Pointer;
import java.io.File;
import java.util.ArrayList;

//--------------------------------------------------
/**
 *ManageDataSet Class Módulo que gestiona el Procesamiento sobre el DataSet
 */
public class ManageDataSet
{
    //--------------------------------------------------
    /**
     * Puntero de entrada de la cámara
     */
    public static Pointer camDev;
    /**
     * Número de Frames almacenados en el buffer de <b>Background Subtraction</b>
     */
    public static int frames = 10;
    /**
     * Bandera de salida del sistema
     */
    public static int salida = 0;
    /**
     * Ancho de la imagen
     */
    public static int W;
    /**
     * Alto de la imagen
     */
    public static int H;
    /**
     * Longitud del arreglo de la imagen <b>(W*H)</b>
     */
    public static int L;
    /**
     * Variable para obtener los datos del frame actual
     */
    public static IplImage image_ptr;
    /**
     * Array en el cual se va a almacenar los datos del frame
     */
    public static float[] buffer;
    /**
     * Array de la imagen original para la máscara
     */
    public static float[] bufferOrigin;
    /**
     * Pointer en el cual se va a almacenar el frame en escala de grises
     */
    public static Pointer image_gray;
    /**
     * Array de la imagen de destino para las etiquetas
     */
    public static float[] img_label;
    /**
     * Promedio de la imagen de fondo
     */
    public static float avgBG=0.0f;
    /**
     * Mediana de la imagen de fondo
     */
    public static float varBG=0.0f;
    /**
     * Imagen de fondo
     */
    public static float[] bufferBg;
    /**
     * Imagen resultado del <b>Background Subtraction</b>
     */
    public static float[] bufferBgS;
    /**
     * Umbral para la binarización, entre <b>(0-1)</b>
     */
    public static float Threshold = 0.3f;

    //--------------------------------------------------
    /**
     * Carga, Preproceso y procesamiento de puntos SIFT y SURF para los videos
     */
    public static void Test_video()
    {
        cv.loadHighgui();
        cv.loadCv();
        cv.loadCxcore();        
        String full_path;        
        ArrayList<String> Videos = new ArrayList<String>();

        ListDir("../DataSet", Videos, ".avi");  //Dirección del DataSet

        //Para todos los videos
        int n;
        for(n = 0; n < Videos.size(); n++)
        {
            full_path = Videos.get(n);
            System.out.println("Video "+(n+1)+": \""+full_path+"\"");
            VideoFile(full_path);
            double fps = cv.GetCaptureProperty(camDev, cv.CV_CAP_PROP_FPS);
            System.out.println("Fps: "+fps+"\n");
            Iniciar();
            byte[] bufferByte = new byte[L];
            int time=1;

            //Bucle de proceso frame a frame
            while(true)
            {                
                Pointer ptr_ima = cv.queryFrame(camDev);
                if(ptr_ima == null)
                    break;
                image_ptr = new IplImage(ptr_ima);
                cv.cvtColor(image_ptr.getPointer(), image_gray, cv.CV_BGR2GRAY);
                bufferByte = Core.Pointer2Byte(image_gray);
                for(int k=0; k<L; k++)
                {
                    if(bufferByte[k]<0)
                        buffer[k] = bufferByte[k] & 255;
                    else
                        buffer[k] = bufferByte[k];
                }
                System.arraycopy(buffer, 0, bufferOrigin, 0, L);
                buffer = Core.LowPassFilter(buffer, Core.lp_kernel,W, H);
                buffer = Core.MedianFilter(buffer, 3, W, H);
                Core.BackgroundSubtractionLearning(buffer, bufferBg, bufferBgS, avgBG, varBG, Threshold);
                bufferBgS = Core.ErosionFilter(Core.kernel3_H, bufferBgS, W, H);
                bufferBgS = Core.DilatationFilter(Core.kernel7_Circle, bufferBgS, W, H);
                float[] labels = Core.LabeledRegions(img_label, bufferBgS, W, H);
                Core.RemoveRegions(img_label, labels,W,H);
                img_label = Core.MaskImage(img_label, bufferOrigin);

                FloatArray2D Desc1 = new FloatArray2D(img_label, W, H);
                Surf.run(Desc1);
                FloatArray2D Desc2 = new FloatArray2D(img_label, W, H);
                SIFT_ExtractPointRoi.run(Desc2);
                //=======
                Save_Interest_Points_To_File FilePoints = new Save_Interest_Points_To_File();
                FilePoints.SurfFile(time, full_path);
                FilePoints.SiftFile(time, full_path);
                time++;
            }
        }
        System.exit(0);
    }

    //--------------------------------------------------
    /**
     * Proceso principal
     * @param args Argumento Línea de Comando
     */
    public static void main(String[] args)
    {        
        Test_video();
    }

    //--------------------------------------------------
    /**
     * Enlista los directorios y archivos de los videos
     * @param path Dirección de los archivos
     * @param dirs Lista donde se almacenan las direcciones
     * @param fileType Tipo de archivo que se enlista
     */
    public static void ListDir(String path, ArrayList<String> dirs, String fileType)
    {
        String t = path;
        File f = new File(t);
        if(f.isDirectory())
        {
            String[] fn = f.list();
            for(int i=0; i< fn.length; i++)
            {                
                t = path+"/"+fn[i];
                ListDir(t, dirs,fileType);
            }
        }
        else if(f.isFile())
        {
            if(path.substring(path.length()-fileType.length(), path.length()).equals(fileType))
                dirs.add(path);
        }
    }

    //--------------------------------------------------
    /**
     * Accede al archivo de video y comprueba su disponibilidad
     * @param path Dirección del archivo
     */
    public static void VideoFile(String path)
    {
        camDev = cv.CreateFileCapture(path);        
        if(camDev==null)
        {
            System.out.println("No camera conected");
            System.exit(0);
        }
        else
        {
            System.out.println("Camera conected");
        }
    }

    //--------------------------------------------------
    /**
     * Inicializa las variables de proceso
     */
    public static void Iniciar()
    {
        image_ptr = new IplImage(cv.queryFrame(camDev));
        H = image_ptr.height;
        W = image_ptr.width;
        L = W * H;        
        buffer = new float[L];
        bufferOrigin = new float[L];
        image_gray = cv.createImage(W, H, 8, 1);
        bufferBgS = new float[L];
        bufferBg = Core.MakeBufferBgLearning(Core.lp_kernel, camDev, buffer, frames, image_ptr, image_gray, L, W, H);
        avgBG = Core.avgImage(bufferBg);
        varBG = Core.varImage(bufferBg, avgBG);
        img_label = new float[L];
    }
}
//--------------------------------------------------
//FIN
//--------------------------------------------------